1
2
3
4
5
6
7 package io.vavr.collection;
8
9 import io.vavr.Tuple;
10 import io.vavr.Tuple2;
11 import io.vavr.control.Option;
12 import org.assertj.core.api.IterableAssert;
13 import org.junit.Test;
14 import org.junit.runner.RunWith;
15 import org.junit.runners.Parameterized;
16
17 import java.util.*;
18 import java.util.function.BiConsumer;
19 import java.util.function.BinaryOperator;
20 import java.util.function.Function;
21 import java.util.function.Supplier;
22 import java.util.regex.Pattern;
23 import java.util.stream.Collector;
24
25 import static java.util.Arrays.asList;
26
27 @RunWith(Parameterized.class)
28 public abstract class AbstractMultimapTest extends AbstractTraversableTest {
29
30 @Parameterized.Parameters
31 public static Collection<Object[]> data() {
32 return asList(new Object[][] {
33 { Multimap.ContainerType.SEQ },
34 { Multimap.ContainerType.SET },
35 { Multimap.ContainerType.SORTED_SET }
36 });
37 }
38
39 @Parameterized.Parameter
40 public Multimap.ContainerType containerType;
41
42 @Override
43 protected <T> IterableAssert<T> assertThat(Iterable<T> actual) {
44 return new IterableAssert<T>(actual) {
45 @Override
46 public IterableAssert<T> isEqualTo(Object obj) {
47 @SuppressWarnings("unchecked")
48 final Iterable<T> expected = (Iterable<T>) obj;
49 final java.util.Map<T, Integer> actualMap = countMap(actual);
50 final java.util.Map<T, Integer> expectedMap = countMap(expected);
51 assertThat(actualMap.size()).isEqualTo(expectedMap.size());
52 actualMap.forEach((k, v) -> assertThat(v).isEqualTo(expectedMap.get(k)));
53 return this;
54 }
55
56 private java.util.Map<T, Integer> countMap(Iterable<? extends T> it) {
57 final java.util.HashMap<T, Integer> cnt = new java.util.HashMap<>();
58 it.forEach(i -> cnt.merge(i, 1, (v1, v2) -> v1 + v2));
59 return cnt;
60 }
61 };
62 }
63
64 @Override
65 protected <T> Collector<T, ArrayList<T>, IntMultimap<T>> collector() {
66 final Collector<Tuple2<Integer, T>, ArrayList<Tuple2<Integer, T>>, ? extends Multimap<Integer, T>> mapCollector = mapCollector();
67 return new Collector<T, ArrayList<T>, IntMultimap<T>>() {
68 @Override
69 public Supplier<ArrayList<T>> supplier() {
70 return ArrayList::new;
71 }
72
73 @Override
74 public BiConsumer<ArrayList<T>, T> accumulator() {
75 return ArrayList::add;
76 }
77
78 @Override
79 public BinaryOperator<ArrayList<T>> combiner() {
80 return (left, right) -> fromTuples(mapCollector.combiner().apply(toTuples(left), toTuples(right)));
81 }
82
83 @Override
84 public Function<ArrayList<T>, IntMultimap<T>> finisher() {
85 return AbstractMultimapTest.this::ofAll;
86 }
87
88 @Override
89 public java.util.Set<Characteristics> characteristics() {
90 return mapCollector.characteristics();
91 }
92
93 private ArrayList<Tuple2<Integer, T>> toTuples(java.util.List<T> list) {
94 final ArrayList<Tuple2<Integer, T>> result = new ArrayList<>();
95 Stream.ofAll(list)
96 .zipWithIndex()
97 .map(tu -> Tuple.of(tu._2, tu._1))
98 .forEach(result::add);
99 return result;
100 }
101
102 private ArrayList<T> fromTuples(java.util.List<Tuple2<Integer, T>> list) {
103 final ArrayList<T> result = new ArrayList<>();
104 Stream.ofAll(list)
105 .map(tu -> tu._2)
106 .forEach(result::add);
107 return result;
108 }
109 };
110 }
111
112 @Override
113 protected <T> IntMultimap<T> empty() {
114 return IntMultimap.of(emptyMap());
115 }
116
117 @Override
118 protected boolean emptyShouldBeSingleton() {
119 return false;
120 }
121
122 private <T> Multimap<Integer, T> emptyInt() {
123 return emptyMap();
124 }
125
126 protected Multimap<Integer, Integer> emptyIntInt() {
127 return emptyMap();
128 }
129
130 private Multimap<Integer, String> emptyIntString() {
131 return emptyMap();
132 }
133
134 abstract protected String className();
135
136 abstract <T1, T2> java.util.Map<T1, T2> javaEmptyMap();
137
138 protected String containerName() {
139 switch (containerType) {
140 case SEQ:
141 return "List";
142 case SET:
143 return "HashSet";
144 case SORTED_SET:
145 return "TreeSet";
146 default:
147 throw new RuntimeException();
148 }
149 }
150
151 protected <T1 extends Comparable<T1>, T2> Multimap<T1, T2> emptyMap() {
152 return emptyMap(Comparators.naturalComparator());
153 }
154
155 abstract protected <T1 extends Comparable<T1>, T2> Multimap<T1, T2> emptyMap(Comparator<? super T2> comparator);
156
157 protected boolean emptyMapShouldBeSingleton() {
158 return true;
159 }
160
161 abstract protected <T> Collector<Tuple2<Integer, T>, ArrayList<Tuple2<Integer, T>>, ? extends Multimap<Integer, T>> mapCollector();
162
163 @SuppressWarnings("unchecked")
164 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOfTuples(Tuple2<? extends K, ? extends V>... entries);
165
166 @SuppressWarnings("unchecked")
167 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOfEntries(java.util.Map.Entry<? extends K, ? extends V>... entries);
168
169 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOfPairs(K k1, V v1, K k, V v2, K k3, V v3);
170
171 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapOf(K key, V value);
172
173 abstract protected <K extends Comparable<? super K>, V> Multimap<K, V> mapOf(java.util.Map<? extends K, ? extends V> map);
174
175 abstract protected <T, K extends Comparable<? super K>, V> Multimap<K, V> mapOf(java.util.stream.Stream<? extends T> stream,
176 Function<? super T, ? extends K> keyMapper,
177 Function<? super T, ? extends V> valueMapper);
178
179 abstract protected <T, K extends Comparable<? super K>, V> Multimap<K, V> mapOf(java.util.stream.Stream<? extends T> stream,
180 Function<? super T, Tuple2<? extends K, ? extends V>> f);
181
182 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapTabulate(int n, Function<? super Integer, ? extends Tuple2<? extends K, ? extends V>> f);
183
184 abstract protected <K extends Comparable<K>, V> Multimap<K, V> mapFill(int n, Supplier<? extends Tuple2<? extends K, ? extends V>> s);
185
186 @Override
187 protected boolean useIsEqualToInsteadOfIsSameAs() {
188 return true;
189 }
190
191 @Override
192 protected int getPeekNonNilPerformingAnAction() {
193 return 1;
194 }
195
196 @Override
197 protected <T> IntMultimap<T> of(T element) {
198 Multimap<Integer, T> map = emptyMap();
199 map = map.put(0, element);
200 return IntMultimap.of(map);
201 }
202
203 @SuppressWarnings("unchecked")
204 @Override
205 protected <T> IntMultimap<T> of(T... elements) {
206 Multimap<Integer, T> map = emptyMap();
207 for (T element : elements) {
208 map = map.put(map.size(), element);
209 }
210 return IntMultimap.of(map);
211 }
212
213 @Override
214 protected <T> IntMultimap<T> ofAll(Iterable<? extends T> elements) {
215 Multimap<Integer, T> map = emptyMap();
216 int i = 0;
217 for (T element : elements) {
218 map = map.put(i++, element);
219 }
220 return IntMultimap.of(map);
221 }
222
223 @Override
224 protected <T extends Comparable<? super T>> IntMultimap<T> ofJavaStream(java.util.stream.Stream<? extends T> javaStream) {
225 return ofAll(io.vavr.collection.Iterator.ofAll(javaStream.iterator()));
226 }
227
228 @Override
229 protected IntMultimap<Boolean> ofAll(boolean... elements) {
230 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
231 }
232
233 @Override
234 protected IntMultimap<Byte> ofAll(byte... elements) {
235 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
236 }
237
238 @Override
239 protected IntMultimap<Character> ofAll(char... elements) {
240 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
241 }
242
243 @Override
244 protected IntMultimap<Double> ofAll(double... elements) {
245 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
246 }
247
248 @Override
249 protected IntMultimap<Float> ofAll(float... elements) {
250 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
251 }
252
253 @Override
254 protected IntMultimap<Integer> ofAll(int... elements) {
255 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
256 }
257
258 @Override
259 protected IntMultimap<Long> ofAll(long... elements) {
260 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
261 }
262
263 @Override
264 protected IntMultimap<Short> ofAll(short... elements) {
265 return ofAll(io.vavr.collection.Iterator.ofAll(elements));
266 }
267
268 @Override
269 protected <T> IntMultimap<T> tabulate(int n, Function<? super Integer, ? extends T> f) {
270 Multimap<Integer, T> map = emptyMap();
271 for (int i = 0; i < n; i++) {
272 map = map.put(map.size(), f.apply(i));
273 }
274 return IntMultimap.of(map);
275 }
276
277 @Override
278 protected <T> IntMultimap<T> fill(int n, Supplier<? extends T> s) {
279 return tabulate(n, anything -> s.get());
280 }
281
282
283
284 @Test
285 public void shouldBeTheSame() {
286 assertThat(mapOf(1, 2)).isEqualTo(emptyIntInt().put(1, 2));
287 }
288
289 private static java.util.Map.Entry<String, Integer> entry(String key, Integer value) {
290 return new java.util.AbstractMap.SimpleEntry<>(key, value);
291 }
292
293 @SuppressWarnings("unchecked")
294 @Test
295 public void shouldConstructFromEntries() {
296 final Multimap<String, Integer> map = mapOfEntries(entry("1", 1), entry("2", 2), entry("3", 3));
297 assertThat(map).isEqualTo(this.<String, Integer> emptyMap().put("1", 1).put("2", 2).put("3", 3));
298 }
299
300 @Test
301 public void shouldConstructFromPairs() {
302 final Multimap<String, Integer> map = mapOfPairs("1", 1, "2", 2, "3", 3);
303 assertThat(map).isEqualTo(this.<String, Integer> emptyMap().put("1", 1).put("2", 2).put("3", 3));
304 }
305
306 @Test
307 public void shouldConstructFromJavaStream() {
308 final java.util.stream.Stream<Integer> javaStream = java.util.stream.Stream.of(1, 2, 3);
309 final Multimap<String, Integer> map = mapOf(javaStream, String::valueOf, Function.identity());
310 assertThat(map).isEqualTo(this.<String, Integer> emptyMap().put("1", 1).put("2", 2).put("3", 3));
311 }
312
313 @Test
314 public void shouldConstructFromJavaStreamEntries() {
315 final java.util.stream.Stream<Integer> javaStream = java.util.stream.Stream.of(1, 2, 3);
316 final Multimap<String, Integer> map = mapOf(javaStream, i -> Tuple.of(String.valueOf(i), i));
317 assertThat(map).isEqualTo(this.<String, Integer> emptyMap().put("1", 1).put("2", 2).put("3", 3));
318 }
319
320 @Test
321 public void shouldConstructFromJavaMap() {
322 final java.util.Map<String, Integer> source = new java.util.HashMap<>();
323 source.put("1", 2);
324 source.put("3", 4);
325 final Multimap<String, Integer> map = mapOf(source);
326 assertThat(map).isEqualTo(this.<String, Integer> emptyMap().put("1", 2).put("3", 4));
327 }
328
329
330
331 @Test
332 public void shouldMakeString() {
333 assertThat(emptyMap().toString()).isEqualTo(className() + "()");
334 assertThat(emptyIntInt().put(1, 2).toString()).isEqualTo(className() + "(" + Tuple.of(1, 2) + ")");
335 }
336
337
338
339 @Test
340 public void shouldConvertToJavaMap() {
341 final Multimap<String, Integer> vavr = mapOfPairs("1", 1, "2", 2, "3", 3);
342 final java.util.Map<String, java.util.Collection<Integer>> java = javaEmptyMap();
343 java.put("1", javaListOf(1));
344 java.put("2", javaListOf(2));
345 java.put("3", javaListOf(3));
346 assertThat(vavr.toJavaMap()).isEqualTo(java);
347 }
348
349 private java.util.Collection<Integer> javaListOf(Integer i) {
350 final java.util.Collection<Integer> list;
351 switch (containerType) {
352 case SEQ:
353 list = new ArrayList<>();
354 break;
355 case SET:
356 list = new java.util.HashSet<>();
357 break;
358 case SORTED_SET:
359 list = new java.util.TreeSet<>();
360 break;
361 default:
362 throw new RuntimeException();
363 }
364 list.add(i);
365 return list;
366 }
367
368
369
370 @Test
371 public void shouldApplyExistingKey() {
372 assertThat(emptyIntInt().put(1, 2).apply(1)).isEqualTo(io.vavr.collection.HashSet.of(2));
373 }
374
375 @Test(expected = NoSuchElementException.class)
376 public void shouldApplyNonExistingKey() {
377 emptyIntInt().put(1, 2).apply(3);
378 }
379
380
381
382 @Test
383 public void shouldFindKey() {
384 assertThat(emptyIntInt().put(1, 2).containsKey(1)).isTrue();
385 assertThat(emptyIntInt().put(1, 2).containsKey(2)).isFalse();
386 }
387
388 @Test
389 public void shouldFindValue() {
390 assertThat(emptyIntInt().put(1, 2).containsValue(2)).isTrue();
391 assertThat(emptyIntInt().put(1, 2).containsValue(1)).isFalse();
392 }
393
394 @Test
395 public void shouldRecognizeNotContainedKeyValuePair() {
396 final Multimap<String, Integer> testee = mapOf("one", 1);
397 assertThat(testee.contains(Tuple.of("one", 0))).isFalse();
398 }
399
400 @Test
401 public void shouldRecognizeContainedKeyValuePair() {
402 final Multimap<String, Integer> testee = mapOf("one", 1);
403 assertThat(testee.contains(Tuple.of("one", 1))).isTrue();
404 }
405
406
407
408 @Test
409 public void shouldObeyEqualityConstraints() {
410
411
412 assertThat(emptyMap().equals(HashMultimap.withSeq().empty())).isTrue();
413 assertThat(mapOf(1, "a").equals(HashMultimap.withSeq().of(1, "a"))).isTrue();
414 assertThat(mapOfPairs(1, "a", 2, "b", 3, "c").equals(HashMultimap.withSeq().of(1, "a", 2, "b",3, "c"))).isTrue();
415 assertThat(mapOfPairs(1, "a", 2, "b", 3, "c").equals(HashMultimap.withSeq().of(3, "c", 2, "b",1, "a"))).isTrue();
416
417
418 assertThat(empty().equals(io.vavr.collection.List.empty())).isFalse();
419 assertThat(empty().equals(HashMap.empty())).isFalse();
420 assertThat(empty().equals(io.vavr.collection.HashSet.empty())).isFalse();
421
422 assertThat(empty().equals(LinkedHashMap.empty())).isFalse();
423 assertThat(empty().equals(io.vavr.collection.LinkedHashSet.empty())).isFalse();
424
425 assertThat(empty().equals(TreeMap.empty())).isFalse();
426 assertThat(empty().equals(TreeSet.empty())).isFalse();
427 }
428
429
430
431 @SuppressWarnings("unchecked")
432 @Test
433 public void shouldFlatMapUsingBiFunction() {
434 final Multimap<Integer, Integer> testee = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33));
435 final Multimap<String, String> actual = testee
436 .flatMap((k, v) -> io.vavr.collection.List.of(Tuple.of(String.valueOf(k), String.valueOf(v)),
437 Tuple.of(String.valueOf(k * 10), String.valueOf(v * 10))));
438 final Multimap<String, String> expected = mapOfTuples(Tuple.of("1", "11"), Tuple.of("10", "110"), Tuple.of("2", "22"),
439 Tuple.of("20", "220"), Tuple.of("3", "33"), Tuple.of("30", "330"));
440 assertThat(actual).isEqualTo(expected);
441 }
442
443
444
445 @SuppressWarnings("unchecked")
446 @Test
447 public void shouldReturnsKeySet() {
448 final Set<Integer> actual = mapOfTuples(Tuple.of(1, 11), Tuple.of(2, 22), Tuple.of(3, 33)).keySet();
449 assertThat(actual).isEqualTo(io.vavr.collection.HashSet.of(1, 2, 3));
450 }
451
452
453
454 @Test
455 public void shouldBiMapEmpty() {
456 assertThat(emptyInt().bimap(i -> i + 1, o -> o)).isEqualTo(io.vavr.collection.Vector.empty());
457 }
458
459 @Test
460 public void shouldBiMapNonEmpty() {
461 final Seq<Tuple2<Integer, String>> expected = Stream.of(Tuple.of(2, "1!"), Tuple.of(3, "2!"));
462 final Seq<Tuple2<Integer, String>> actual = emptyInt().put(1, "1").put(2, "2").bimap(i -> i + 1, s -> s + "!").toStream();
463 assertThat(actual).isEqualTo(expected);
464 }
465
466
467
468 @Test
469 public void shouldMapEmpty() {
470 assertThat(emptyInt().map(Tuple2::_1)).isEqualTo(io.vavr.collection.Vector.empty());
471 }
472
473 @Test
474 public void shouldMapNonEmpty() {
475 final Seq<Integer> expected = io.vavr.collection.Vector.of(1, 2);
476 final Seq<Integer> actual = emptyInt().put(1, "1").put(2, "2").map(Tuple2::_1);
477 assertThat(actual).isEqualTo(expected);
478 }
479
480 @Test
481 public void shouldMapComparableValues() {
482 final Multimap<Integer, String> map = this.<Integer, String>emptyMap()
483 .put(1, "1")
484 .put(1, "2")
485 .put(2, "3");
486 assertThat(map.map(v -> v)).isEqualTo(io.vavr.collection.List.of(
487 Tuple.of(1, "1"),
488 Tuple.of(1, "2"),
489 Tuple.of(2, "3")));
490 }
491
492 @Test
493 public void shouldMapIncomparableValues() {
494 final Multimap<Integer, Incomparable> map = this.<Integer, Incomparable>emptyMap(Comparator.comparing(Incomparable::getS))
495 .put(1, new Incomparable("1"))
496 .put(1, new Incomparable("2"))
497 .put(2, new Incomparable("3"));
498 assertThat(map.map(v -> v)).isEqualTo(io.vavr.collection.List.of(
499 Tuple.of(1, new Incomparable("1")),
500 Tuple.of(1, new Incomparable("2")),
501 Tuple.of(2, new Incomparable("3"))));
502 }
503
504 private final static class Incomparable {
505 private String s;
506
507 Incomparable(String s) {
508 this.s = s;
509 }
510
511 public String getS() {
512 return s;
513 }
514
515 @Override
516 public boolean equals(Object o) {
517 return o == this || (o instanceof Incomparable && Objects.equals(s, ((Incomparable) o).s));
518 }
519
520 @Override
521 public int hashCode() {
522 return Objects.hashCode(s);
523 }
524 }
525
526 @Test
527 public void shouldReturnEmptySetWhenAskedForTuple2SetOfAnEmptyMap() {
528 assertThat(emptyMap().toSet()).isEqualTo(io.vavr.collection.HashSet.empty());
529 }
530
531 @Test
532 public void shouldReturnTuple2SetOfANonEmptyMap() {
533 assertThat(emptyInt().put(1, "1").put(2, "2").toSet()).isEqualTo(io.vavr.collection.HashSet.of(Tuple.of(1, "1"), Tuple.of(2, "2")));
534 }
535
536 @Test
537 public void shouldReturnModifiedValuesMap() {
538 assertThat(emptyIntString().put(1, "1").put(2, "2").mapValues(Integer::parseInt)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2));
539 }
540
541 @Test
542 public void shouldReturnListWithMappedValues() {
543 assertThat(emptyIntInt().put(1, 1).put(2, 2).iterator((a, b) -> a + b)).isEqualTo(io.vavr.collection.List.of(2, 4));
544 }
545
546
547
548 @Test
549 public void shouldMerge() {
550 final Multimap<Integer, Integer> m1 = emptyIntInt().put(1, 1).put(2, 2);
551 final Multimap<Integer, Integer> m2 = emptyIntInt().put(1, 1).put(4, 4);
552 final Multimap<Integer, Integer> m3 = emptyIntInt().put(3, 3).put(4, 4);
553 assertThat(emptyIntInt().merge(m2)).isEqualTo(m2);
554 assertThat(m2.merge(emptyIntInt())).isEqualTo(m2);
555 if (containerType == Multimap.ContainerType.SEQ) {
556 assertThat(m1.merge(m2)).isEqualTo(emptyIntInt().put(1, 1).put(1, 1).put(2, 2).put(4, 4));
557 assertThat(m1.merge(m3)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4));
558 } else {
559 assertThat(m1.merge(m2)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(4, 4));
560 assertThat(m1.merge(m3)).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4));
561 }
562 }
563
564 @SuppressWarnings("unchecked")
565 @Test
566 public void shouldMergeCollisions() {
567 final Multimap<Integer, Integer> m1 = emptyIntInt().put(1, 1).put(2, 2);
568 final Multimap<Integer, Integer> m2 = emptyIntInt().put(1, 2).put(4, 4);
569 final Multimap<Integer, Integer> m3 = emptyIntInt().put(3, 3).put(4, 4);
570 assertThat(emptyIntInt().merge(m2, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(m2);
571 assertThat(m2.merge(emptyIntInt(), (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(m2);
572 assertThat(m1.merge(m2, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(emptyIntInt().put(1, 1).put(1, 2).put(2, 2).put(4, 4));
573 assertThat(m1.merge(m3, (s1, s2) -> io.vavr.collection.Iterator.concat(s1, s2))).isEqualTo(emptyIntInt().put(1, 1).put(2, 2).put(3, 3).put(4, 4));
574 }
575
576
577
578
579 @Override
580 @Test
581 public void shouldCaclEmptyOrElseSameOther() {
582 Iterable<Integer> other = of(42);
583 assertThat(empty().orElse(other)).isEqualTo(other);
584 }
585
586 @Test
587 public void shouldCaclEmptyOrElseSameSupplier() {
588 Iterable<Integer> other = of(42);
589 Supplier<Iterable<Integer>> supplier = () -> other;
590 assertThat(empty().orElse(supplier)).isEqualTo(other);
591 }
592
593
594
595 @Test
596 public void shouldIgnoreOrderOfEntriesWhenComparingForEquality() {
597 final Multimap<?, ?> map1 = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c');
598 final Multimap<?, ?> map2 = emptyInt().put(3, 'c').put(2, 'b').put(1, 'a').remove(2).put(2, 'b');
599 assertThat(map1).isEqualTo(map2);
600 }
601
602
603
604 @Test
605 public void shouldPutTuple() {
606 assertThat(emptyIntInt().put(Tuple.of(1, 2))).isEqualTo(emptyIntInt().put(1, 2));
607 }
608
609
610
611 @Test
612 public void shouldRemoveKey() {
613 final Multimap<Integer, Object> src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c');
614 assertThat(src.remove(2)).isEqualTo(emptyInt().put(1, 'a').put(3, 'c'));
615 assertThat(src.remove(33)).isSameAs(src);
616 }
617
618
619
620 @Test
621 public void shouldReplaceEntity() {
622 final Multimap<Integer, Object> actual = emptyInt().put(1, "a").put(1, "b").replace(Tuple.of(1, "a"), Tuple.of(1, "c"));
623 final Multimap<Integer, Object> expected = emptyInt().put(1, "c").put(1, "b");
624 assertThat(actual).isEqualTo(expected);
625 }
626
627
628
629 @Test
630 public void shouldRemoveAllKeys() {
631 final Multimap<Integer, Object> src = emptyInt().put(1, 'a').put(2, 'b').put(3, 'c');
632 assertThat(src.removeAll(io.vavr.collection.List.of(1, 3))).isEqualTo(emptyInt().put(2, 'b'));
633 assertThat(src.removeAll(io.vavr.collection.List.of(33))).isSameAs(src);
634 assertThat(src.removeAll(io.vavr.collection.List.empty())).isSameAs(src);
635 }
636
637
638
639 @Test
640 public void shouldReturnSameInstanceIfReplacingCurrentValueWithNonExistingKey() {
641 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b");
642 final Multimap<Integer, String> actual = map.replaceValue(3, "?");
643 assertThat(actual).isSameAs(map);
644 }
645
646 @Test
647 public void shouldReplaceCurrentValueForExistingKey() {
648 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b");
649 final Multimap<Integer, String> actual = map.replaceValue(2, "c");
650 final Multimap<Integer, String> expected = mapOf(1, "a").put(2, "c");
651 assertThat(actual).isEqualTo(expected);
652 }
653
654 @Test
655 public void shouldReplaceValuesWithNewValueForExistingKey() {
656 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b").put(2, "c");
657 final Multimap<Integer, String> actual = map.replaceValue(2, "c");
658 final Multimap<Integer, String> expected = mapOf(1, "a").put(2, "c");
659 assertThat(actual).isEqualTo(expected);
660 }
661
662
663
664 @Test
665 public void shouldReplaceCurrentValueForExistingKeyAndEqualOldValue() {
666 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b");
667 final Multimap<Integer, String> actual = map.replace(2, "b", "c");
668 final Multimap<Integer, String> expected = mapOf(1, "a").put(2, "c");
669 assertThat(actual).isEqualTo(expected);
670 }
671
672 @Test
673 public void shouldReplaceCurrentValueForKeyWithMultipleValuesAndEqualOldValue() {
674 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b").put(2, "d");
675 final Multimap<Integer, String> actual = map.replace(2, "b", "c");
676 final Multimap<Integer, String> expected = mapOf(1, "a").put(2, "c").put(2, "d");
677 assertThat(actual).isEqualTo(expected);
678 }
679
680 @Test
681 public void shouldReturnSameInstanceForExistingKeyAndNonEqualOldValue() {
682 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b");
683 final Multimap<Integer, String> actual = map.replace(2, "d", "c");
684 assertThat(actual).isSameAs(map);
685 }
686
687 @Test
688 public void shouldReturnSameInstanceIfReplacingCurrentValueWithOldValueWithNonExistingKey() {
689 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b");
690 final Multimap<Integer, String> actual = map.replace(3, "?", "!");
691 assertThat(actual).isSameAs(map);
692 }
693
694
695
696 @Test
697 public void shouldReplaceAllValuesWithFunctionResult() {
698 final Multimap<Integer, String> map = mapOf(1, "a").put(2, "b").put(2, "c");
699 final Multimap<Integer, String> actual = map.replaceAll((integer, s) -> s + integer);
700 final Multimap<Integer, String> expected = mapOf(1, "a1").put(2, "b2").put(2, "c2");
701 assertThat(actual).isEqualTo(expected);
702 }
703
704
705
706 @Test
707 public void shouldTransform() {
708 final Multimap<?, ?> actual = emptyIntInt().put(1, 11).transform(map -> map.put(2, 22));
709 assertThat(actual).isEqualTo(emptyIntInt().put(1, 11).put(2, 22));
710 }
711
712
713
714 @Test
715 public void shouldUnzipNil() {
716 assertThat(emptyMap().unzip(x -> Tuple.of(x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty()));
717 assertThat(emptyMap().unzip((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v))))
718 .isEqualTo(Tuple.of(Stream.empty(), Stream.empty()));
719 }
720
721 @Test
722 public void shouldUnzipNonNil() {
723 final Multimap<Integer, Integer> map = emptyIntInt().put(0, 0).put(1, 1);
724 final Tuple actual = map.unzip(entry -> Tuple.of(entry._1, entry._2 + 1));
725 final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2));
726 assertThat(actual).isEqualTo(expected);
727 }
728
729 @Test
730 public void shouldUnzip3Nil() {
731 assertThat(emptyMap().unzip3(x -> Tuple.of(x, x, x))).isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty()));
732 assertThat(emptyMap().unzip3((k, v) -> Tuple.of(Tuple.of(k, v), Tuple.of(k, v), Tuple.of(k, v))))
733 .isEqualTo(Tuple.of(Stream.empty(), Stream.empty(), Stream.empty()));
734 }
735
736 @Test
737 public void shouldUnzip3NonNil() {
738 final Multimap<Integer, Integer> map = emptyIntInt().put(0, 0).put(1, 1);
739 final Tuple actual = map.unzip3(entry -> Tuple.of(entry._1, entry._2 + 1, entry._2 + 5));
740 final Tuple expected = Tuple.of(Stream.of(0, 1), Stream.of(1, 2), Stream.of(5, 6));
741 assertThat(actual).isEqualTo(expected);
742 }
743
744
745
746 @Test
747 public void shouldZipNils() {
748 final Seq<Tuple2<Tuple2<Integer, Integer>, Object>> actual = emptyIntInt().zip(io.vavr.collection.List.empty());
749 assertThat(actual).isEqualTo(Stream.empty());
750 }
751
752 @Test
753 public void shouldZipEmptyAndNonNil() {
754 final Seq<Tuple2<Tuple2<Integer, Integer>, Integer>> actual = emptyIntInt().zip(io.vavr.collection.List.of(1));
755 assertThat(actual).isEqualTo(Stream.empty());
756 }
757
758 @Test
759 public void shouldZipNonEmptyAndNil() {
760 final Seq<Tuple2<Tuple2<Integer, Integer>, Object>> actual = emptyIntInt().put(0, 1).zip(io.vavr.collection.List.empty());
761 assertThat(actual).isEqualTo(Stream.empty());
762 }
763
764 @Test
765 public void shouldZipNonNilsIfThisIsSmaller() {
766 final Seq<Tuple2<Tuple2<Integer, Integer>, Integer>> actual = emptyIntInt()
767 .put(0, 0)
768 .put(1, 1)
769 .zip(io.vavr.collection.List.of(5, 6, 7));
770 assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6)));
771 }
772
773 @Test
774 public void shouldZipNonNilsIfThatIsSmaller() {
775 final Seq<Tuple2<Tuple2<Integer, Integer>, Integer>> actual = emptyIntInt()
776 .put(0, 0)
777 .put(1, 1)
778 .put(2, 2)
779 .zip(io.vavr.collection.List.of(5, 6));
780 assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6)));
781 }
782
783 @Test
784 public void shouldZipNonNilsOfSameSize() {
785 final Seq<Tuple2<Tuple2<Integer, Integer>, Integer>> actual = emptyIntInt()
786 .put(0, 0)
787 .put(1, 1)
788 .put(2, 2)
789 .zip(io.vavr.collection.List.of(5, 6, 7));
790 assertThat(actual).isEqualTo(
791 Stream.of(Tuple.of(Tuple.of(0, 0), 5), Tuple.of(Tuple.of(1, 1), 6), Tuple.of(Tuple.of(2, 2), 7)));
792 }
793
794 @Test(expected = NullPointerException.class)
795 public void shouldThrowIfZipWithThatIsNull() {
796 emptyMap().zip(null);
797 }
798
799
800
801 @Test
802 public void shouldZipNilWithIndex() {
803 assertThat(emptyMap().zipWithIndex()).isEqualTo(Stream.empty());
804 }
805
806 @Test
807 public void shouldZipNonNilWithIndex() {
808 final Seq<Tuple2<Tuple2<Integer, Integer>, Integer>> actual = emptyIntInt()
809 .put(0, 0)
810 .put(1, 1)
811 .put(2, 2)
812 .zipWithIndex();
813 assertThat(actual).isEqualTo(
814 Stream.of(Tuple.of(Tuple.of(0, 0), 0), Tuple.of(Tuple.of(1, 1), 1), Tuple.of(Tuple.of(2, 2), 2)));
815 }
816
817
818
819 @Test
820 public void shouldZipAllNils() {
821 final Seq<Tuple2<Tuple2<Integer, Integer>, Object>> actual = emptyIntInt().zipAll(empty(), null, null);
822 assertThat(actual).isEqualTo(Stream.empty());
823 }
824
825 @Test
826 public void shouldZipAllEmptyAndNonNil() {
827 final Seq<Tuple2<Tuple2<Integer, Integer>, Object>> actual = emptyIntInt().zipAll(io.vavr.collection.List.of(1), null, null);
828 assertThat(actual).isEqualTo(Stream.of(Tuple.of(null, 1)));
829 }
830
831 @Test
832 public void shouldZipAllNonEmptyAndNil() {
833 final Seq<Tuple2<Tuple2<Integer, Integer>, Object>> actual = emptyIntInt().put(0, 1).zipAll(empty(), null, null);
834 assertThat(actual).isEqualTo(Stream.of(Tuple.of(Tuple.of(0, 1), null)));
835 }
836
837 @Test
838 public void shouldZipAllNonNilsIfThisIsSmaller() {
839 final Seq<Tuple2<Tuple2<Integer, Object>, String>> actual = this.<Integer, Object> emptyMap()
840 .put(1, 1)
841 .put(2, 2)
842 .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z");
843 final Seq<Tuple2<Tuple2<Object, Object>, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"),
844 Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c"));
845 assertThat(actual).isEqualTo(expected);
846 }
847
848 @Test
849 public void shouldZipAllNonNilsIfThisIsMoreSmaller() {
850 final Seq<Tuple2<Tuple2<Integer, Object>, String>> actual = this.<Integer, Object> emptyMap()
851 .put(1, 1)
852 .put(2, 2)
853 .zipAll(of("a", "b", "c", "d"), Tuple.of(9, 10), "z");
854 final Seq<Tuple2<Tuple2<Object, Object>, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"),
855 Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(9, 10), "c"), Tuple.of(Tuple.of(9, 10), "d"));
856 assertThat(actual).isEqualTo(expected);
857 }
858
859 @Test
860 public void shouldZipAllNonNilsIfThatIsSmaller() {
861 final Seq<Tuple2<Tuple2<Integer, Object>, String>> actual = this.<Integer, Object> emptyMap()
862 .put(1, 1)
863 .put(2, 2)
864 .put(3, 3)
865 .zipAll(this.of("a", "b"), Tuple.of(9, 10), "z");
866 final Seq<Tuple2<Tuple2<Object, Object>, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"),
867 Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z"));
868 assertThat(actual).isEqualTo(expected);
869 }
870
871 @Test
872 public void shouldZipAllNonNilsIfThatIsMoreSmaller() {
873 final Seq<Tuple2<Tuple2<Integer, Object>, String>> actual = this.<Integer, Object> emptyMap()
874 .put(1, 1)
875 .put(2, 2)
876 .put(3, 3)
877 .put(4, 4)
878 .zipAll(of("a", "b"), Tuple.of(9, 10), "z");
879 final Seq<Tuple2<Tuple2<Object, Object>, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"),
880 Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "z"), Tuple.of(Tuple.of(4, 4), "z"));
881 assertThat(actual).isEqualTo(expected);
882 }
883
884 @Test
885 public void shouldZipAllNonNilsOfSameSize() {
886 final Seq<Tuple2<Tuple2<Integer, Object>, String>> actual = this.<Integer, Object> emptyMap()
887 .put(1, 1)
888 .put(2, 2)
889 .put(3, 3)
890 .zipAll(of("a", "b", "c"), Tuple.of(9, 10), "z");
891 final Seq<Tuple2<Tuple2<Object, Object>, String>> expected = Stream.of(Tuple.of(Tuple.of(1, 1), "a"),
892 Tuple.of(Tuple.of(2, 2), "b"), Tuple.of(Tuple.of(3, 3), "c"));
893 assertThat(actual).isEqualTo(expected);
894 }
895
896 @Test(expected = NullPointerException.class)
897 public void shouldThrowIfZipAllWithThatIsNull() {
898 emptyMap().zipAll(null, null, null);
899 }
900
901
902
903 @Override
904 public void shouldComputeDistinctOfNonEmptyTraversable() {
905 final Multimap<Integer, Object> testee = this.<Integer, Object> emptyMap().put(1, 1).put(2, 2).put(3, 3);
906 assertThat(testee.distinct()).isEqualTo(testee);
907 }
908
909 @Override
910 public void shouldReturnSomeTailWhenCallingTailOptionOnNonNil() {
911 assertThat(of(1, 2, 3).tailOption().get()).isEqualTo(Option.some(of(2, 3)).get());
912 }
913
914 @Override
915 public void shouldPreserveSingletonInstanceOnDeserialization() {
916
917 }
918
919 @Override
920 public void shouldFoldRightNonNil() {
921 final String actual = of('a', 'b', 'c').foldRight("", (x, xs) -> x + xs);
922 final io.vavr.collection.List<String> expected = io.vavr.collection.List.of('a', 'b', 'c').permutations().map(io.vavr.collection.List::mkString);
923 assertThat(actual).isIn(expected);
924 }
925
926
927
928 @Test
929 public void forEachByKeyValue() {
930 final Multimap<Integer, Integer> map = mapOf(1, 2).put(3, 4);
931 final int[] result = { 0 };
932 map.forEach((k, v) -> result[0] += k + v);
933 assertThat(result[0]).isEqualTo(10);
934 }
935
936 @Test
937 public void forEachByTuple() {
938 final Multimap<Integer, Integer> map = mapOf(1, 2).put(3, 4);
939 final int[] result = { 0 };
940 map.forEach(t -> result[0] += t._1 + t._2);
941 assertThat(result[0]).isEqualTo(10);
942 }
943
944 @SuppressWarnings("unchecked")
945 @Test
946 public void shouldTabulateTheSeq() {
947 final Function<Number, Tuple2<Long, Float>> f = i -> new Tuple2<>(i.longValue(), i.floatValue());
948 final Multimap<Long, Float> map = mapTabulate(3, f);
949 assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f)));
950 }
951
952 @SuppressWarnings("unchecked")
953 @Test
954 public void shouldTabulateTheSeqCallingTheFunctionInTheRightOrder() {
955 final LinkedList<Integer> ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2));
956 final Function<Integer, Tuple2<Long, Float>> f = i -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue());
957 final Multimap<Long, Float> map = mapTabulate(3, f);
958 assertThat(map).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f)));
959 }
960
961 @Test
962 public void shouldTabulateTheSeqWith0Elements() {
963 assertThat(mapTabulate(0, i -> new Tuple2<>(i, i))).isEqualTo(empty());
964 }
965
966 @Test
967 public void shouldTabulateTheSeqWith0ElementsWhenNIsNegative() {
968 assertThat(mapTabulate(-1, i -> new Tuple2<>(i, i))).isEqualTo(empty());
969 }
970
971 @SuppressWarnings("unchecked")
972 @Test
973 public void shouldFillTheSeqCallingTheSupplierInTheRightOrder() {
974 final LinkedList<Integer> ints = new LinkedList<>(asList(0, 0, 1, 1, 2, 2));
975 final Supplier<Tuple2<Long, Float>> s = () -> new Tuple2<>(ints.remove().longValue(), ints.remove().floatValue());
976 final Multimap<Long, Float> actual = mapFill(3, s);
977 assertThat(actual).isEqualTo(mapOfTuples(new Tuple2<>(0L, 0f), new Tuple2<>(1L, 1f), new Tuple2<>(2L, 2f)));
978 }
979
980 @Test
981 public void shouldFillTheSeqWith0Elements() {
982 assertThat(mapFill(0, () -> new Tuple2<>(1, 1))).isEqualTo(empty());
983 }
984
985 @Test
986 public void shouldFillTheSeqWith0ElementsWhenNIsNegative() {
987 assertThat(mapFill(-1, () -> new Tuple2<>(1, 1))).isEqualTo(empty());
988 }
989
990
991
992 @Test
993 public void shouldHoldEqualsElements() {
994 Multimap<Integer, String> multimap = emptyMap();
995 multimap = multimap.put(1, "a").put(1, "b").put(1, "b");
996 if (containerType == Multimap.ContainerType.SEQ) {
997 assertThat(multimap.toString()).isEqualTo(className() + "((1, a), (1, b), (1, b))");
998 } else {
999 assertThat(multimap.toString()).isEqualTo(className() + "((1, a), (1, b))");
1000 }
1001 }
1002
1003
1004
1005 @Test
1006 public void shouldBiFilterWork() throws Exception {
1007 final Multimap<Integer, String> src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n)));
1008 final Pattern isDigits = Pattern.compile("^\\d+$");
1009 final Multimap<Integer, String> dst = src.filter((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches());
1010 assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(2, "2").put(4, "4").put(6, "6").put(6, "10").put(8, "8").put(8, "12"));
1011 }
1012
1013 @Test
1014 public void shouldKeyFilterWork() throws Exception {
1015 final Multimap<Integer, String> src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n)));
1016 final Multimap<Integer, String> dst = src.filterKeys(k -> k % 2 == 0);
1017 assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(0, "a").put(2, "2").put(2, "c").put(4, "4").put(4, "e").put(6, "6").put(6, "10").put(8, "8").put(8, "12"));
1018 }
1019
1020 @Test
1021 public void shouldValueFilterWork() throws Exception {
1022 final Multimap<Integer, String> src = mapTabulate(10, n -> Tuple.of(n % 5, Integer.toHexString(n)));
1023 final Pattern isDigits = Pattern.compile("^\\d+$");
1024 final Multimap<Integer, String> dst = src.filterValues(v -> isDigits.matcher(v).matches());
1025 assertThat(dst).isEqualTo(emptyIntString().put(0, "0").put(0, "5").put(1, "1").put(1, "6").put(2, "2").put(2, "7").put(3, "3").put(3, "8").put(4, "4").put(4, "9"));
1026 }
1027
1028
1029
1030 @Test
1031 public void shouldBiRemoveWork() throws Exception {
1032 final Multimap<Integer, String> src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n)));
1033 final Pattern isDigits = Pattern.compile("^\\d+$");
1034 final Multimap<Integer, String> dst = src.removeAll((k, v) -> k % 2 == 0 && isDigits.matcher(v).matches());
1035 assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "1").put(1, "b").put(2, "c").put(3, "3").put(3, "d").put(4, "e").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13"));
1036 }
1037
1038 @Test
1039 public void shouldKeyRemoveWork() throws Exception {
1040 final Multimap<Integer, String> src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n)));
1041 final Multimap<Integer, String> dst = src.removeKeys(k -> k % 2 == 0);
1042 assertThat(dst).isEqualTo(emptyIntString().put(1, "1").put(1, "b").put(3, "3").put(3, "d").put(5, "5").put(5, "f").put(7, "7").put(7, "11").put(9, "9").put(9, "13"));
1043 }
1044
1045 @Test
1046 public void shouldValueRemoveWork() throws Exception {
1047 final Multimap<Integer, String> src = mapTabulate(20, n -> Tuple.of(n % 10, Integer.toHexString(n)));
1048 final Pattern isDigits = Pattern.compile("^\\d+$");
1049 final Multimap<Integer, String> dst = src.removeValues(v -> isDigits.matcher(v).matches());
1050 assertThat(dst).isEqualTo(emptyIntString().put(0, "a").put(1, "b").put(2, "c").put(3, "d").put(4, "e").put(5, "f"));
1051 }
1052
1053
1054
1055 @Test
1056 public void shouldReturnDefaultValue() {
1057 final Multimap<String, String> map = mapOf("1", "a").put("2", "b");
1058 assertThat(map.getOrElse("3", io.vavr.collection.List.of("3"))).isEqualTo(io.vavr.collection.List.of("3"));
1059 }
1060
1061
1062
1063 @Override
1064 @Test
1065 public void shouldCreateSeqOfSeqUsingCons() {
1066
1067
1068 }
1069
1070 @Override
1071 @Test
1072 public void shouldConvertToJavaArrayWithTypeHintPrimitiveVoid() {
1073
1074
1075 }
1076
1077
1078
1079 @Test
1080 public void shouldHaveSizedSpliterator() {
1081 assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED)).isTrue();
1082 }
1083
1084 @Test
1085 public void shouldHaveDistinctSpliterator() {
1086 assertThat(of(1, 2, 3).spliterator().hasCharacteristics(Spliterator.DISTINCT)).isTrue();
1087 }
1088
1089 @Test
1090 public void shouldReturnSizeWhenSpliterator() {
1091 assertThat(of(1, 2, 3).spliterator().getExactSizeIfKnown()).isEqualTo(3);
1092 }
1093
1094 @Override
1095 @Test
1096 @SuppressWarnings("unchecked")
1097 public void shouldPartitionIntsInOddAndEvenHavingOddAndEvenNumbers() {
1098 assertThat(of(1, 2, 3, 4).partition(i -> i % 2 != 0))
1099 .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 1), Tuple.of(2, 3)),
1100 mapOfTuples(Tuple.of(1, 2), Tuple.of(3, 4))));
1101 }
1102
1103 @Override
1104 @Test
1105 @SuppressWarnings("unchecked")
1106 public void shouldSpanNonNil() {
1107 assertThat(of(0, 1, 2, 3).span(i -> i < 2))
1108 .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0, 0), Tuple.of(1, 1)),
1109 mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 3))));
1110 }
1111
1112 @Override
1113 @Test
1114 @SuppressWarnings("unchecked")
1115 public void shouldSpanAndNotTruncate() {
1116 assertThat(of(1, 1, 2, 2, 3, 3).span(x -> x % 2 == 1))
1117 .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)),
1118 mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2),
1119 Tuple.of(4, 3), Tuple.of(5, 3))));
1120 assertThat(of(1, 1, 2, 2, 4, 4).span(x -> x == 1))
1121 .isEqualTo(Tuple.of(mapOfTuples(Tuple.of(0,1), Tuple.of(1, 1)),
1122 mapOfTuples(Tuple.of(2, 2), Tuple.of(3, 2),
1123 Tuple.of(4, 4), Tuple.of(5, 4))));
1124 }
1125
1126 @Override
1127 @Test
1128 public void shouldNonNilGroupByIdentity() {
1129 final Map<?, ?> actual = of('a', 'b', 'c').groupBy(Function.identity());
1130 final Map<?, ?> expected = LinkedHashMap.empty().put('a', mapOf(0, 'a')).put('b', mapOf(1,'b'))
1131 .put('c', mapOf(2,'c'));
1132 assertThat(actual).isEqualTo(expected);
1133 }
1134 }